﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SimpleActor.Test
{
    [TestClass]
    public class ActionMessageTest
    {
        [TestMethod]
        public void InvokeTest()
        {
            var servant = new TestServant();
            servant.GetParameter().Result.IsNull();

            var obj = new ActionMessage<ITestServant>("Action0", s => s.Action0());
            obj.MethodName.Is("Action0");
            obj.Task.Status.Is(TaskStatus.WaitingForActivation);

            obj.Invoke(servant);
            obj.Task.Status.Is(TaskStatus.RanToCompletion);
            servant.GetParameter().Result.Is(Unit.Default);
        }

        [TestMethod]
        public void InvokeTestException()
        {
            var servant = new TestServant();
            servant.GetParameter().Result.IsNull();

            var obj = new ActionMessage<ITestServant>("Action0ThrowsException", s => s.Action0ThrowsException());
            obj.MethodName.Is("Action0ThrowsException");
            obj.Task.Status.Is(TaskStatus.WaitingForActivation);

            AssertEx.Throws<SampleException>(() => obj.Invoke(servant));
            obj.Task.Status.Is(TaskStatus.Faulted);
            obj.Task.Exception.InnerException.IsInstanceOf<SampleException>();
        }

        [TestMethod]
        public void AbortTest()
        {
            var ex = new SampleException();
            Func<Exception> newException = () => ex;

            var obj = new ActionMessage<ITestServant>("Action0", s => s.Action0());
            obj.MethodName.Is("Action0");
            obj.Task.Status.Is(TaskStatus.WaitingForActivation);

            obj.Abort(newException);
            obj.Task.Status.Is(TaskStatus.Faulted);
            obj.Task.Exception.InnerException.IsSameReferenceAs(ex);
        }
    }
}
